import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;


public class CommunicationChannel {
	Socket socket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    int timeoutms = 300000;
    ConnectionDetails connDetails = new ConnectionDetails();
    
    public CommunicationChannel()
    {
    	
    }
    
    public CommunicationChannel(ConnectionDetails connDetails, int waitTimeoutms)
    {
    	this.connDetails = connDetails;
    	this.timeoutms = waitTimeoutms;
    }
    
    public CommunicationChannel(ConnectionDetails connDetails)
    {
    	this.connDetails = connDetails;
    }
    
    public boolean openSocketOutIn()
    {
    	try{
		    this.socket = new Socket(connDetails.hostNameOrIP, connDetails.port);
		    this.socket.setSoTimeout(timeoutms);
		    this.out = new PrintWriter(socket.getOutputStream(), true);
		    this.in = new BufferedReader(new InputStreamReader(
		                                socket.getInputStream()));
	    } catch (UnknownHostException e){
	    	System.out.println("Could not open connection with " + 
	    			connDetails.hostNameOrIP + ":" + connDetails.port + ". " +
	    			"Unknown host.");
        	return false;
        } catch(IOException e){
        	System.out.println("Could not open connection with " + 
	    			connDetails.hostNameOrIP + ":" + connDetails.port + ". " +
	    			"IO exception.");
        	return false;
        } catch(Exception e){
        	System.out.println("Could not open connection with " + 
	    			connDetails.hostNameOrIP + ":" + connDetails.port + ". " +
	    			"Exception.");
        	return false;
        }
        return true;
    }
    
    public boolean closeSocketOutIn()
    {
    	out.close();
		try{
			in.close();
			socket.close();
		} catch (UnknownHostException e){
        	e.printStackTrace();
        	return false;
        } catch(IOException e){
        	e.printStackTrace();
        	return false;
        } catch(Exception e){
        	e.printStackTrace();
        	return false;
        }
        return true;
    }
    
    public String sendMessageRcvReply(String message) {
		//throws UnknownHostException, IOException
	    
	    out.println(message);
	    String reply = null;
	    try{
	    	reply = in.readLine();	//should timeout because the socket.setSoTimeout is set above
	    }
	    catch(SocketTimeoutException e){
	    	System.out.println("Timed out waiting for reply from " + 
	    			connDetails.hostNameOrIP + ":" + connDetails.port);
	    } catch (UnknownHostException e){
        	e.printStackTrace();
        } catch(IOException e){
        	e.printStackTrace();
        } catch(Exception e){
        	e.printStackTrace();
        }
	    
		return reply;	//reply will be null if a timeout occurred
	}
    
    public void sendMessage(String message)
    {
        out.println(message);
	}
}
